package model

import (
	"easyVolunteer/utils/code"
	"easyVolunteer/utils/errno"
	"fmt"
	"gorm.io/gorm"
	"log"
)

type UserLogin struct {
	UserID   string `gorm:"primaryKey;type:BIGINT;" json:"userID" validate:"required,len=10,numeric" label:"用户名"`
	PassWord string `gorm:"type:varchar(65);NOT NULL" json:"passWord" validate:"required,min=6,max=20" label:"密码"`
}

type UserInfo struct {
	UserID          string `gorm:"primaryKey;foreignKey;type:BIGINT; comment: 学生ID" validate:"required,len=10" label:"用户名"`
	Name            string `gorm:"type:varchar(10);NOT NULL；comment:姓名" validate:"min=2,max=4" label:"姓名"`
	GeneralInfoCode string `gorm:"type:BIGINT;comment:通用信息识别码" json:"generalInfoCode" validate:"min=2" label:"通用信息码"`
}

type User struct {
	UserID     string     `gorm:"primaryKey;foreignKey;type:BIGINT;NOT NULL; comment:学生ID" json:"userID" validate:"required,len=10"`
	Role       uint8      `gorm:"type:TINYINT;DEFAULT = 1;NOT NULL; 用户角色，控制权限" json:"role" validate:"oneof=1 2"`
	TotalHours float32    `gorm:"type:FLOAT;DEFAULT = 0;NOT NULL; comment:用户累计时长" json:"totalHours"`
	Activities []Activity `gorm:"many2many:activities_users;references:activity_id;" json:"activities"`
	UserInfo   UserInfo   `json:"userInfo"`
}

// CreateUser 添加新用户
func CreateUser(u *User) *errno.Errno {
	err := globalDb.Create(u)
	if err != nil {
		log.Println(" 添加新用户失败", u, err)
		return errno.ErrDatabase
	}
	return errno.OK
}

// GetUserRole 查询用户权限
func GetUserRole(userID uint64) (uint8, *errno.Errno) {
	var u User
	//u.UserID = userID
	err := globalDb.Select("role").First(&u, userID).Error
	if err != nil {
		return 0, errno.ErrDatabase
	}

	return u.Role, errno.OK
}

// JoinActivity 用户加入活动
func JoinActivity(activityID uint64, userID string) *errno.Errno {
	// 构造出用户和活动模型
	u := User{UserID: userID}
	a := Activity{ActivityID: activityID}

	// 执行减库存-更新用户和活动的映射关系
	err := globalDb.Transaction(func(tx *gorm.DB) error {
		// 判断活动库存
		if row := tx.Model(&a).Where("stock > ?", 0).Update("stock", gorm.Expr("stock - ?", 1)).RowsAffected; row == 0 {
			fmt.Println(row)
			err := tx.Model(&a).Where("stock = ?", 0).Update("status", code.ActivityRunning).Error
			return err
		}
		// 关联操作
		if err := tx.Model(&a).Association("Users").Append(&u); err != nil {
			fmt.Println(err)
			return err
		}
		return nil
	})

	if err != nil {
		return errno.ErrDatabase
	}

	return errno.OK
}

// QuitActivity 用户退出活动招募
func QuitActivity(activityID uint64, userID string) *errno.Errno {

	u := User{UserID: userID}
	a := Activity{ActivityID: activityID}

	err := globalDb.Transaction(func(tx *gorm.DB) error {
		if err := tx.Model(&a).Where("stock < limits").Update("stock", gorm.Expr("stock + ?", 1)).Error; err != nil {
			return err
		}
		if err := tx.Model(&u).Association("Activities").Delete(&a); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return errno.ErrDatabase
	}
	return errno.OK
}

// GetUserAllActivity 获得用户参加的所有的志愿者活动
func GetUserAllActivity(userID string) ([]Activity, *errno.Errno) {
	u := User{UserID: userID}
	var activities []Activity

	err := globalDb.Model(&u).Association("Activities").Find(&activities)

	if err != nil {
		return nil, errno.Fail
	}
	return activities, errno.OK
}

// SyncAllActivityHours 同步用户总的时长
func SyncAllActivityHours(userID string) *errno.Errno {
	activities, status := GetUserAllActivity(userID)

	if status != errno.OK {
		return status
	}

	u := User{UserID: userID}

	var total float32
	for _, i := range activities {
		if i.Status == code.ActivityFinished {
			total += i.Duration
		}
	}
	err := globalDb.Model(&u).Update("total_hours", total).Error
	if err != nil {
		return errno.Fail
	}
	return errno.OK
}

// GetUserHour 查询用户名下的总时长
func GetUserHour(userID string) (float32, *errno.Errno) {
	u := User{UserID: userID}

	err := globalDb.Select("total_hours").First(&u).Error
	if err != nil {
		return 0, errno.Fail
	}
	return u.TotalHours, errno.OK
}

func GetUserIfJoinActivity(activityID uint64, userID string) bool {
	u := User{UserID: userID}
	//a := Activity{ActivityID: activityID}

	count := globalDb.Model(&u).Where("activity_id = ? ", activityID).Association("Activities").Count()
	//fmt.Println("关联计数是", count)
	if count == 0 {
		// 计数为零，说明未参加活动
		return false
	}

	// 关联计数不为 0 说明已经参加活动
	return true
}

// FindUserVolunteerInfo 查找用户信息
func FindUserVolunteerInfo(userID string) (UserInfo, *errno.Errno) {
	var u UserInfo
	u.UserID = userID
	err := globalDb.Model(&UserInfo{}).First(&u).Error
	if err != nil {
		return UserInfo{}, errno.ErrDatabase
	}

	return u, errno.OK
}

// CalculateSummaryData 按照不同学院或者不同班级，统计一定时间范围内的志愿者时长信息
func CalculateSummaryData(generalInfoCode, start, end string, pageNum, pageSize int) ([]User, *errno.Errno) {
	// 考虑到活动少，所以，以活动为核心查找范围合法的用户
	// 预加载UserInfo和User

	var u []User
	globalDb.Model(&User{}).
		Joins("INNER JOIN t_user_infos ON t_users.user_id = t_user_infos.user_id AND t_user_infos.general_info_code like ?", generalInfoCode+"%").
		//Preload("UserInfo").
		Preload("Activities", "start > ? AND end < ?", start, end).
		Find(&u).
		Limit(pageSize).
		Offset((pageNum - 1) * pageSize)

	return u, errno.OK
}

// FindUserInfo 所在学院、专业这些信息
func FindUserInfo(id string) (UserInfo, *errno.Errno) {
	var u UserInfo
	err := globalDb.Model(&u).First(&u, id).Error
	if err != nil {
		return UserInfo{}, errno.ErrDatabase
	}

	return u, errno.OK
}
